// Gaia Ajax Widgets Copyright (C) 2007  Frost Innovation AS. details at http://ajaxwidgets.com/
/* 
 * Gaia Ajax Widgets, an Ajax Widget Library
 * Copyright (C) 2007  Frost Innovation AS
 * All rights reserved.
 * This program is distributed under either GPL version 2 
 * as published by the Free Software Foundation or the
 * Gaia Commercial License version 1 as published by
 * Frost Innovation AS
 * read the details at http://ajaxwidgets.com/
 */



/* ---------------------------------------------------------------------------
   Class basically wrapping a RichEdit WebControl class
   --------------------------------------------------------------------------- */
Gaia.RichEdit = function(element, options){
  this.initialize(element, options);
}

// Inheriting from WebControl
Object.extend(Gaia.RichEdit.prototype, Gaia.WebControl.prototype);

// Adding custom parts
Object.extend(Gaia.RichEdit.prototype, {
  // "Constructor"
  initialize: function(element, options){
    // Calling base class constructor
    this.baseInitializeWebControl(element, options);

    this.element.contentWindow.document.open();

    this.element.contentWindow.document.write('<html xmlns="http://www.w3.org/1999/xhtml"><head>');

    if( this.options.cssFile )
      this.element.contentWindow.document.write('<link id="cssFile" rel="stylesheet" media="screen" type="text/css" href="' + this.options.cssFile + '"/>');

    this.element.contentWindow.document.write('</head><body style="margin:0;padding:0">');

    if( this.options.text )
      this.element.contentWindow.document.write(this.options.text);

    this.element.contentWindow.document.write('</body></html>');

    this.element.contentWindow.document.close();

    if( this.element.contentWindow.document.designMode ) {
      // FireFox
      this.element.contentWindow.document.designMode = "on";
    } else {
      // IE and Opera
      this.element.contentWindow.document.body.contentEditable = true;
    }

    // Making sure we'll trap SUBMIT behaviour TOO
    this.onSubmit = this.submit.bind(this);
    Element.observe(document.forms[0], 'submit', this.onSubmit);

    // For submit behaviour to be trapped we need a HIDDEN field which we 
    // manipulate the value of just before the form is being submitted
    var cont = document.createElement('input');
    cont.type = 'hidden';
    cont.id = this.element.id + '_VALUE';
    cont.name = cont.id;
    document.getElementsByTagName('form')[0].appendChild(cont);

    // To ensure focus is given to RichEdit control
    setTimeout(function(){
      this.setFocus();

      // Catching blur to maintain selected text across events...
      this.onBlur = this.blur.bind(this);
      Element.observe(document.body, 'mousedown', this.onBlur);

    }.bind(this), 1000);
  },

  setCssFile: function(value){
    this.options.cssFile = value;
    this.element.contentWindow.document.getElementById('cssFile').href = value;
    return this;
  },

  blur: function(){
    this.activeElement = this.element.contentWindow.document.activeElement;
    if(window.getSelection) {
      // FF && Opera....!
      var sel = this.element.contentWindow.getSelection();
      if( sel.rangeCount > 0 ){
        this.currentRange = sel.getRangeAt(0);
      }
    }
    else if(document.selection) {
      // IE
      this.currentRange = this.element.contentWindow.document.selection.createRange();
    }

    // Subscribing to the MouseDown event
    this.onClick = this.click.bind(this);
    Element.observe(this.element.contentWindow.document, 'mousedown', this.onClick);
    Element.stopObserving(document.body, 'mousedown', this.onBlur);
    delete this.onBlur;
  },

  click: function(){

    // Catching blur to maintain selected text across events...
    this.onBlur = this.blur.bind(this);
    Element.observe(document.body, 'mousedown', this.onBlur);

    // Stopping 'click'
    Element.stopObserving(this.element.contentWindow.document, 'mousedown', this.onClick);
    delete this.onClick;
  },

  execCommand: function(cmd, ui, vValue){
    if(window.getSelection) {
      // Opera and FF....!!
      this.element.contentWindow.document.execCommand(cmd, ui, vValue);
    } else {
      // IE ONLY...!!
      if( this.currentRange )
        this.currentRange.execCommand(cmd, ui, vValue);
      else
        this.element.contentWindow.document.execCommand(cmd, ui, vValue);
    }
    return this;
  },

  // Either replaces the currently selected text or pastes in at the caret's position the given "value" HTML
  pasteHtml: function(value){
    if (window.getSelection){
      // FF AND Opera....!!
      var range;
      if( this.currentRange ) {
        range = this.currentRange;
      } else {
        var sel = this.element.contentWindow.getSelection();
        range = sel.getRangeAt(0);
      }
      var content = this.element.contentWindow.document.createElement('span');
      content.innerHTML = value;
      range.deleteContents();
      range.insertNode(content);
    }
    else if(document.selection) {
      // IE
      if( this.currentRange ) {
        this.currentRange.select();
        this.currentRange.pasteHTML(value);
      }
      else
        this.element.contentWindow.document.selection.createRange().pasteHTML(value);
    }
    return this;
  },

  submit: function(){
    var cont = $(this.element.id + '_VALUE');
    var value = this.getElementValue();

    // Escaping Carriage Returns
    while( value.indexOf('\r\n') != -1 ){
      value = value.replace('\r\n', '{n|n|');
    }
    while( value.indexOf('\n') != -1 ){
      value = value.replace('\n', '{n|n|');
    }
    cont.value = value;
  },

  // Sets text of RichEdit
  setText: function(value){
    this.element.contentWindow.document.body.innerHTML = value;
    return this;
  },

  // Sets the tabindex of the control
  setTabIndex: function(value){
    this.element.tabIndex = value;
    return this;
  },
  
  setFocus: function(){
    try{
      if( navigator.userAgent.toLowerCase().indexOf('opera') != -1 )
        this.element.focus();
      else
        this.element.contentWindow.focus();
    } 
    catch (err) { }
    return this;
  },

  getSelectedText: function(){
    if(window.getSelection) {
      if( this.element.contentWindow.document.getSelection ){
        // FF
        return this.element.contentWindow.document.getSelection();
      } else {
        // Safari
        return this.element.contentWindow.getSelection();
      }
    } else {
      // IE
      return this.element.contentWindow.document.selection.createRange().text;
    }    
  },

  getElementValue: function(){
    var value = this.element.contentWindow.document.body.innerHTML;

    // Escaping ALL anglebrackets to not choke our server security...
    while( value.indexOf('<') != -1 ){
      value = value.replace('<', '{||');
    }
    while( value.indexOf('>') != -1 ){
      value = value.replace('>', '||}');
    }
    return value;
  },

  _getElementPostValue: function(){
    var retVal = '&' + encodeURIComponent(this.element.id + '_VALUE') + '=' + encodeURIComponent(this.getElementValue()) + 
      '&' + encodeURIComponent(this.element.id + '_SELECTED') + '=' + encodeURIComponent(this.getSelectedText());
    return retVal;
  }
});

Gaia.RichEdit.browserFinishedLoading = true;
